﻿using Newtonsoft.Json;
using PhilipService;
using PhilipSupport.Controls.MainControl;
using PhilipSupport.Entity;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using System.Windows.Forms;
using TCommon;
using TCommon.Util;
using PhilipService.Entity;
using System.Diagnostics;
using System.Text;

namespace PhilipSupport
{
    public partial class SupportMain : Form
    {
        private OnLineStatus status = OnLineStatus.Online;
        private bool isStatusBtnShow = false;
        private Stack<Control> formStack = new Stack<Control>();
        private WSocketClient client = null;

        public SupportMain()
        {
            InitializeComponent();
            PhilipContext.supportMain = this;
            formStack.Push(mainControl);
            panel_head.MouseDown += Panel_head_MouseDown;
            panel_head.MouseMove += Panel_head_MouseMove;
            label_title.MouseDown += Panel_head_MouseDown;
            label_title.MouseMove += Panel_head_MouseMove;

            panel_main.MouseMove += SupportMain_MouseMove;
            mainControl.MouseMove += SupportMain_MouseMove;
            mainControl.MyInfoClicked += MainControl_MyInfoClicked;
            mainControl.ServiceReocrdClicked += MainControl_ServiceReocrdClicked;
            mainControl.HostMeetingClicked += MainControl_HostMeetingClicked;
        }

        public void SetOnlineStatus(OnLineStatus status) {
            this.status = status;
            UpdateOnlineStatus();
        }

        public void SetStatusButtonsEnable(bool enable) {
            this.btn_busy.Enabled = enable;
            this.btn_offline.Enabled = enable;
            this.btn_online.Enabled = enable;
            this.btn_changeStatus.Enabled = enable;
        }

        public void UpdateTitle(string title) {
            this.label_title.Text = title;
        }

        public void ShowServiceList()
        {
            var last_control = formStack.ElementAt(0);
            if (last_control is ServiceRecords) {
                RemoveControl();
            }
            var serviceRecord = new ServiceRecords();
            serviceRecord.ViewDetailClicked += ServiceRecord_ViewDetailClicked;
            AddControl(serviceRecord);
        }

        private void Panel_head_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.Location = new Point(this.Location.X + e.X - downPoint.X,
                    this.Location.Y + e.Y - downPoint.Y);
            }

            if (e.Y <= 3)
            {
                this.Cursor = Cursors.SizeNS;
            }
            else if (e.X <= 3)
            {
                this.Cursor = Cursors.SizeWE;
            }
            else if (e.X <= 3)
            {
                this.Cursor = Cursors.SizeWE;
            }
            else if (e.Y >= this.Height - 3)
            {
                this.Cursor = Cursors.SizeNS;
            }
            else if (e.X >= this.Width - 3)
            {
                this.Cursor = Cursors.SizeWE;
            }
            else
            {
                this.Cursor = Cursors.Default;
            }
        }

        private void Panel_head_MouseDown(object sender, MouseEventArgs e)
        {
            if (isStatusBtnShow)
            {
                UpdateOnlineStatus();
            }
            downPoint = new Point(e.X, e.Y);
        }

        private void MainControl_HostMeetingClicked()
        {
            var meeting = new MeetingMain();
            AddControl(meeting);
        }

        private void MainControl_ServiceReocrdClicked()
        {
            var serviceRecord = new ServiceRecords();
            serviceRecord.ViewDetailClicked += ServiceRecord_ViewDetailClicked;
            AddControl(serviceRecord);
        }

        private void ServiceRecord_ViewDetailClicked(Control control)
        {
            AddControl(control);
        }

        private void MainControl_MyInfoClicked()
        {
            //var form = new QARecordForm();
            //form.TopMost = true;

            //form.Height = Screen.PrimaryScreen.WorkingArea.Height - 30;
            //form.Show();
            //form.Location = new Point(5, 5);

            Task.Factory.StartNew(new Action(() =>
            {
                var manager = new RestServiceManager();
                var res = manager.GetMyInfo(PhilipContext.UserId);
                if (res != null)
                {
                    this.Invoke(new Action(() =>
                    {
                        var myInfo = new MyInfo(res);
                        AddControl(myInfo);
                    }));
                }
            }));
            
        }

        private void btn_online_Click(object sender, EventArgs e)
        {
            if (!isStatusBtnShow)
            {
                ShowStatusButton();
            }
            else
            {
                status = OnLineStatus.Online;
                UpdateOnlineStatus(true);
            }
        }

        private void btn_changeStatus_Click(object sender, EventArgs e)
        {
            if (!isStatusBtnShow)
            {
                ShowStatusButton();
            }
            else
            {
                this.btn_busy.Visible = false;
                this.btn_online.Visible = false;
                this.btn_offline.Visible = false;
                UpdateOnlineStatus();
                isStatusBtnShow = false;
            }
        }

        private void btn_busy_Click(object sender, EventArgs e)
        {
            if (!isStatusBtnShow)
            {
                ShowStatusButton();
            }
            else
            {
                status = OnLineStatus.Busy;
                UpdateOnlineStatus(true);
            }
        }

        private void btn_offline_Click(object sender, EventArgs e)
        {
            if (!isStatusBtnShow)
            {
                ShowStatusButton();
            }
            else
            {
                status = OnLineStatus.Offline;
                UpdateOnlineStatus(true);
            }
        }

        private void ShowStatusButton()
        {
            this.btn_busy.Visible = true;
            this.btn_online.Visible = true;
            this.btn_online.Parent = this;
            this.btn_online.BringToFront();
            this.btn_offline.Visible = true;
            switch (status)
            {
                case OnLineStatus.Online:
                    this.btn_online.Location = new Point(167, 24);
                    this.btn_busy.Location = new Point(167, 54);
                    this.btn_offline.Location = new Point(167, 84);
                    break;
                case OnLineStatus.Busy:
                    this.btn_busy.Location = new Point(167, 24);
                    this.btn_online.Location = new Point(167, 54);
                    this.btn_offline.Location = new Point(167, 84);
                    break;
                case OnLineStatus.Offline:
                    this.btn_offline.Location = new Point(167, 24);
                    this.btn_online.Location = new Point(167, 54);
                    this.btn_busy.Location = new Point(167, 84);
                    break;
            }
            isStatusBtnShow = true;
        }

        private void UpdateOnlineStatus(bool manual = false)
        {
            switch (status)
            {
                case OnLineStatus.Online:
                    this.btn_online.Visible = true;
                    this.btn_online.Location = new Point(167, 24);
                    this.btn_offline.Visible = false;
                    this.btn_busy.Visible = false;
                    if (manual)
                    {
                        PhilipContext.isAvailable = true;
                    }
                    break;
                case OnLineStatus.Busy:
                    this.btn_busy.Visible = true;
                    this.btn_busy.Location = new Point(167, 24);
                    this.btn_online.Visible = false;
                    this.btn_offline.Visible = false;
                    if (manual)
                    {
                        PhilipContext.isAvailable = false;
                    }
                    break;
                case OnLineStatus.Offline:
                    this.btn_offline.Visible = true;
                    this.btn_offline.Location = new Point(167, 24);
                    this.btn_busy.Visible = false;
                    this.btn_online.Visible = false;
                    if (manual)
                    {
                        PhilipContext.isAvailable = false;
                    }
                    break;
            }
            Task.Factory.StartNew(new Action(() =>
            {
                var manager = new RestServiceManager();
                var code = manager.SetStatus(PhilipContext.UserId, (int)status);
                if (code == 1) {
                    this.Invoke(new Action(() =>
                    {
                        MessageBox.Show("修改状态失败");
                    }));
                }
            }));
            isStatusBtnShow = false;
        }

        Point downPoint;

        CFormMouseStatus formMouseStatus = CFormMouseStatus.Nothing;
        Point? mousePosition = null;
        private void SupportMain_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.WindowState == FormWindowState.Maximized)
            {
                this.Cursor = Cursors.Default;
            }
            else
            {
                switch (this.formMouseStatus)
                {
                    case CFormMouseStatus.TopResize:
                        if (this.mousePosition != null)
                        {
                            this.Top += e.Y - this.mousePosition.Value.Y;
                            this.Height -= e.Y - this.mousePosition.Value.Y;
                        }

                        break;
                    case CFormMouseStatus.LeftResize:
                        if (this.mousePosition != null)
                        {
                            this.Left += e.X - this.mousePosition.Value.X;
                            this.Width -= e.X - this.mousePosition.Value.X;
                        }

                        break;
                    case CFormMouseStatus.BottomResize:
                        if (this.mousePosition != null)
                        {
                            this.Height += e.Y - this.mousePosition.Value.Y;
                            this.mousePosition = new Point(e.X, e.Y);
                        }

                        break;
                    case CFormMouseStatus.RightResize:
                        if (this.mousePosition != null)
                        {
                            this.Width += e.X - this.mousePosition.Value.X;
                            this.mousePosition = new Point(e.X, e.Y);
                        }

                        break;
                    default:
                        if (e.Y <= 3)
                        {
                            this.Cursor = Cursors.SizeNS;
                        }
                        else if (e.X <= 3)
                        {
                            this.Cursor = Cursors.SizeWE;
                        }
                        else if (e.X <= 3)
                        {
                            this.Cursor = Cursors.SizeWE;
                        }
                        else if (e.Y >= this.Height - 3)
                        {
                            this.Cursor = Cursors.SizeNS;
                        }
                        else if (e.X >= this.Width - 3)
                        {
                            this.Cursor = Cursors.SizeWE;
                        }
                        else
                        {
                            this.Cursor = Cursors.Default;
                        }

                        break;
                }
            }
        }

        private void SupportMain_MouseDown(object sender, MouseEventArgs e)
        {
            if (isStatusBtnShow)
            {
                UpdateOnlineStatus();
            }

            if (e.Y <= 3)
            {
                this.formMouseStatus = CFormMouseStatus.TopResize;
                this.mousePosition = new Point(e.X, e.Y);
            }
            else if (e.X <= 3)
            {
                this.formMouseStatus = CFormMouseStatus.LeftResize;
                this.mousePosition = new Point(e.X, e.Y);
            }
            else if (e.Y >= this.Height - 3)
            {
                this.formMouseStatus = CFormMouseStatus.BottomResize;
                this.mousePosition = new Point(e.X, e.Y);
            }
            else if (e.X >= this.Width - 2 * 3)
            {
                this.formMouseStatus = CFormMouseStatus.RightResize;
                this.mousePosition = new Point(e.X, e.Y);
            }
            else
            {
                this.formMouseStatus = CFormMouseStatus.Moving;
                this.mousePosition = new Point(e.X, e.Y);
            }
        }

        private void btn_close_Click(object sender, EventArgs e)
        {
            var result = MessageBox.Show("是否确认退出系统？", "确认退出", MessageBoxButtons.YesNo);
            if (result == DialogResult.Yes)
            {
                status = OnLineStatus.Offline;
                UpdateOnlineStatus();
                this.Close();
                Application.Exit();
            }
        }

        private void btn_max_Click(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Maximized)
            {
                this.WindowState = FormWindowState.Normal;
            }
            else
            {
                this.WindowState = FormWindowState.Maximized;
            }
        }

        private void btn_back_Click(object sender, EventArgs e)
        {
            RemoveControl();
        }

        public void RemoveControl() {
            if (formStack.Count > 1)
            {
                var control = formStack.Pop();
                control.MouseMove -= SupportMain_MouseMove;
                panel_main.Controls.Remove(control);
                var last_control = formStack.ElementAt(0);
                last_control.MouseMove += SupportMain_MouseMove;
                last_control.Visible = true;
                UpdateTitle(last_control);
            }
        }

        private void BackToHome() {
            if (formStack.Count > 1)
            {
                var main_control = formStack.ElementAt(formStack.Count - 1);
                formStack.Clear();
                panel_main.Controls.Clear();
                formStack.Push(main_control);
                panel_main.Controls.Add(main_control);
                main_control.Visible = true;
                UpdateTitle(main_control);
                UpdateSize();
            }
        }

        public void AddControl(Control control) {
            control.MouseMove += SupportMain_MouseMove;
            var last_control = formStack.ElementAt(0);
            last_control.MouseMove -= SupportMain_MouseMove;
            formStack.Push(control);
            panel_main.Controls.Add(control);
            UpdateSize();
            control.BringToFront();
            last_control.Visible = false;
            //control.MouseMove += SupportMain_MouseMove;
            //control.MouseDown += SupportMain_MouseDown;
            UpdateTitle(control);

            control.MouseDown += Control_MouseDown;
        }

        private void UpdateTitle(Control control) {
            this.Invoke(new Action(() =>
            {
                if (control is MainControl)
                {
                    label_title.Text = "飞利浦超声应用远程支持系统";
                }
                else if (control is MeetingMain)
                {
                    label_title.Text = "多方连线";
                }
                else if (control is MyInfo)
                {
                    label_title.Text = "我的资料";
                }
                else if (control is ServiceRecords)
                {
                    label_title.Text = "服务记录";
                }
                else if (control is ServiceDetail)
                {
                    label_title.Text = "医生的咨询";
                }
                else if (control is ClientDetail)
                {
                    label_title.Text = "用户详情";
                }
                else if (control is DeviceDetail)
                {
                    label_title.Text = "设备详情";
                }
                else if (control is RecordControl)
                {
                    label_title.Text = "应用笔记";
                }
                else if (control is UserComment)
                {
                    label_title.Text = "用户评价";
                }
            }));
            
        }

        private void Control_MouseDown(object sender, MouseEventArgs e)
        {
            if (isStatusBtnShow) {
                UpdateOnlineStatus();
            }
        }

        private void mainControl_Load(object sender, EventArgs e)
        {
            this.label_username.Text = string.Format("Hi,{0}", PhilipContext.UserName);
            Task.Factory.StartNew(new Action(() =>
            {
                ulong zoomId = 0;
                string meetingId = string.Empty;
                string ownId = string.Empty;

                zoomId = ulong.Parse(PhilipContext.OwnId);
                ownId = PhilipContext.HostId;
                var name = StringUtil.ToHex(string.Format("{0}:{1}", ownId, zoomId));
                TCommon.AppContext.LocalUserName = name;
                TCommon.AppContext.CurrentUser = name;
                var manager = new ServiceManager();
                TCommon.AppContext.UserSign = manager.GetUserSign((int)zoomId, name);
                TCommon.AppContext.LocalRoomId = zoomId.ToString();
            }));
            UpdateOnlineStatus();
            label_title.Font = PhilipContext.CustomFont;
        }

        private void panel_main_SizeChanged(object sender, EventArgs e)
        {
            UpdateSize();
            this.Invalidate();
        }

        private void UpdateSize()
        {
            var width = (int)(panel_main.Width * 0.75);
            var height = (int)(panel_main.Height * 0.75);

            foreach (Control contrl in panel_main.Controls)
            {

                Point location;

                if (contrl is MainControl)
                {
                    contrl.Width = (int)(panel_main.Width * 0.9);
                    contrl.Height = (int)(panel_main.Height * 0.9); 
                    location = new Point((int)(panel_main.Width * 0.1 / 2), (int)(panel_main.Height * 0.1 / 2));
                    contrl.Location = location;
                }
                else if (contrl is MeetingMain)
                {
                    location = new Point((int)((panel_main.Width - contrl.Width) / 2), (int)((panel_main.Height - contrl.Height) / 2));
                    contrl.Location = location;
                }
                else if (contrl is ServiceRecords)
                {
                    contrl.Width = (int)(panel_main.Width * 0.9);
                    contrl.Height = panel_main.Height - 60;
                    location = new Point((int)(panel_main.Width * 0.1 / 2), 20);
                    contrl.Location = location;
                }
                else if (contrl is MyInfo)
                {
                    contrl.Width = width;
                    contrl.Height = height;
                    location = new Point((int)(panel_main.Width * 0.25 / 2), (int)(panel_main.Height * 0.25 / 2));
                    contrl.Location = location;
                }
                else if (contrl is ServiceDetail)
                {
                    contrl.Width = width;
                    contrl.Height = (int)(panel_main.Height * 0.95);
                    location = new Point((int)(panel_main.Width * 0.25 / 2), (int)(panel_main.Height * 0.05 / 2));
                    contrl.Location = location;
                }
                else if (contrl is ClientDetail || contrl is DeviceDetail 
                    || contrl is RecordControl || contrl is UserComment) {
                    contrl.Width = width;
                    contrl.Height = height;
                    location = new Point((int)(panel_main.Width * 0.25 / 2), (int)(panel_main.Height * 0.25 / 2));
                    contrl.Location = location;
                }
            }
        }

        private void SupportMain_Load(object sender, EventArgs e)
        {
            ConnectServer();
            this.MaximizedBounds = Screen.PrimaryScreen.WorkingArea;
        }

        private void SupportMain_Paint(object sender, PaintEventArgs e)
        {
            var pen = new Pen(Color.LightGray);
            e.Graphics.DrawLine(pen, new Point(0, 0), new Point(this.Width, 0));
            e.Graphics.DrawLine(pen, new Point(this.Width - 1, 0), new Point(this.Width - 1, this.Height));
            e.Graphics.DrawLine(pen, new Point(0, this.Height - 1), new Point(this.Width - 1, this.Height - 1));
            e.Graphics.DrawLine(pen, new Point(0, this.Height - 1), new Point(0, 0));
        }

        private void SupportMain_MouseLeave(object sender, EventArgs e)
        {
            this.formMouseStatus = CFormMouseStatus.Nothing;
            this.mousePosition = null;
        }

        private void SupportMain_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.formMouseStatus = CFormMouseStatus.Nothing;
                this.mousePosition = null;
            }
        }

        private void btn_home_Click(object sender, EventArgs e)
        {
            if (PhilipContext.lockForFinishService)
            {
                MessageBox.Show("请先完成该服务");
                return;
            }
            this.BackToHome();
        }

        private void btn_min_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
        }

        private void ConnectServer()
        {
            SetCertificatePolicy();
            //新建客户端类 
            //服务端IP地址 ws://47.96.94.140 如果服务端开启了ssl或者tsl 这里前缀应该改成 wss:/
            //服务端监听端口 9501
            //自定义的地址参数 可以根据地址参数来区分客户端 /lcj控制台
            //开始链接
            try
            {
                client = new WSocketClient("wss://talk.1meeting.com:9501");
                client.MessageReceived += Client_MessageReceived; ;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        public void SendMsg(string msg)
        {
            try
            {
                // System.Windows.MessageBox.Show(msg);
                if (string.IsNullOrEmpty(msg))
                    MessageBox.Show("空值不让传！");
                client.SendMessage(msg);
                // System.Windows.MessageBox.Show("发送成功");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        public static void SetCertificatePolicy()
        {
            ServicePointManager.ServerCertificateValidationCallback
                       += RemoteCertificateValidate;
            // ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
        }

        /// <summary>
        /// Remotes the certificate validate.
        /// </summary>
        private static bool RemoteCertificateValidate(
           object sender, X509Certificate cert,
            X509Chain chain, SslPolicyErrors error)
        {
            // trust any certificate!!!
            System.Console.WriteLine("Warning, trust any certificate");
            return true;
        }

        private void Client_MessageReceived(string obj)
        {
            try
            {
                var baseMsg = JsonConvert.DeserializeObject<BaseMessage>(obj);
                switch (baseMsg.Type)
                {
                    case MessageType.UserCall:
                        var resp = JsonConvert.DeserializeObject<CustomerSupportRequest>(obj);
                        if (resp != null && resp.CustomerId == PhilipContext.UserId)
                        {
                            this.Invoke(new Action(() =>
                            {
                                var form = new CoverForm(resp.CustomerId, resp.UserId, resp.Name, resp.Information, resp.ServiceId, resp.DeviceId);
                                form.Width = this.Width;
                                form.Height = this.Height;
                                form.Location = this.Location;
                                form.Show(this);
                            }));
                        }
                        break;
                    case MessageType.UserEndCall:
                        var endCallResp = JsonConvert.DeserializeObject<UserCancelMessage>(obj);
                        if (endCallResp != null && endCallResp.CustomerId == PhilipContext.UserId)
                        {
                            this.Invoke(new Action(() =>
                            {
                                PhilipContext.callComeForm?.CancelCall();
                            }));
                        }
                        break;
                }
            }
            catch (Exception e) {
                string str = GetExceptionMsg(e);
                MessageBox.Show(str, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            
        }

        private string GetExceptionMsg(Exception ex)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("****************************异常文本****************************");
            sb.AppendLine("【出现时间】：" + DateTime.Now.ToString());
            if (ex != null)
            {
                sb.AppendLine("【异常类型】：" + ex.GetType().Name);
                sb.AppendLine("【异常信息】：" + ex.Message);
                sb.AppendLine("【堆栈调用】：" + ex.StackTrace);
            }
            sb.AppendLine("***************************************************************");
            return sb.ToString();
        }

        private void SupportMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            client?.Stop();
        }
    }

    public enum CFormMouseStatus { Moving, TopResize, LeftResize, BottomResize, RightResize, Nothing };
}
